package util

/**
 * @File : testSet.go
 * @Description : 实现一个使用 map 和空结构体的泛型 Set 结构
 * @Author : Crist
 * @Date : 2024-07-09
 */

// Set 是一个泛型集合结构体，使用 map 存储元素，值为空结构体
type Set[T comparable] struct {
	m map[T]struct{}
}

// NewSet 创建一个新的泛型集合，并初始化内部的 map
func NewSet[T comparable]() *Set[T] {
	return &Set[T]{
		m: make(map[T]struct{}),
	}
}

// Add 向集合中添加一个元素
func (s *Set[T]) Add(value T) {
	s.m[value] = struct{}{} // 使用空结构体，不占用额外存储
}

// Remove 从集合中删除一个元素
func (s *Set[T]) Remove(value T) {
	delete(s.m, value) // 从 map 中删除该元素
}

// Contains 检查集合中是否包含某个元素
func (s *Set[T]) Contains(value T) bool {
	_, exists := s.m[value] // 检查元素是否存在于 map 中
	return exists
}

// Size 返回集合的大小（元素个数）
func (s *Set[T]) Size() int {
	return len(s.m) // 返回 map 的长度
}

// Clear 清空集合
func (s *Set[T]) Clear() {
	s.m = make(map[T]struct{}) // 重新初始化 map，从而清空集合
}

// Elements 返回集合中的所有元素
func (s *Set[T]) Elements() []T {
	keys := make([]T, 0, len(s.m)) // 创建一个切片用于存储元素
	for key := range s.m {
		keys = append(keys, key) // 将 map 中的键（元素）添加到切片中
	}
	return keys
}

//func main() {
//	// 创建一个字符串类型的集合
//	stringSet := NewSet[string]()
//
//	// 向集合中添加元素
//	stringSet.Add("apple")
//	stringSet.Add("banana")
//	stringSet.Add("cherry")
//
//	// 检查元素是否存在
//	fmt.Println("stringSet 包含 'apple' 吗？", stringSet.Contains("apple")) // 输出: true
//	fmt.Println("stringSet 包含 'grape' 吗？", stringSet.Contains("grape")) // 输出: false
//
//	// 获取集合的大小
//	fmt.Println("stringSet 大小:", stringSet.Size()) // 输出: 3
//
//	// 从集合中移除元素
//	stringSet.Remove("banana")
//	fmt.Println("stringSet 大小（移除 'banana' 后）:", stringSet.Size()) // 输出: 2
//
//	// 获取集合中的所有元素
//	fmt.Println("stringSet 元素:", stringSet.Elements()) // 输出: [apple cherry]
//
//	// 清空集合
//	stringSet.Clear()
//	fmt.Println("stringSet 大小（清空后）:", stringSet.Size()) // 输出: 0
//
//	// 创建一个整数类型的集合
//	intSet := NewSet[int]()
//
//	// 向集合中添加元素
//	intSet.Add(1)
//	intSet.Add(2)
//	intSet.Add(3)
//
//	// 检查元素是否存在
//	fmt.Println("intSet 包含 1 吗？", intSet.Contains(1)) // 输出: true
//	fmt.Println("intSet 包含 4 吗？", intSet.Contains(4)) // 输出: false
//
//	// 获取集合的大小
//	fmt.Println("intSet 大小:", intSet.Size()) // 输出: 3
//
//	// 从集合中移除元素
//	intSet.Remove(2)
//	fmt.Println("intSet 大小（移除 2 后）:", intSet.Size()) // 输出: 2
//
//	// 获取集合中的所有元素
//	fmt.Println("intSet 元素:", intSet.Elements()) // 输出: [1 3]
//
//	// 清空集合
//	intSet.Clear()
//	fmt.Println("intSet 大小（清空后）:", intSet.Size()) // 输出: 0
//}
